﻿using DBUtil.FastEntity.Builders;
using DotNetCommon.Data;
using DotNetCommon.Extensions;
using DotNetCommon.Logger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace DBUtil.FastEntity
{
    public abstract class EntityManager
    {
        public EntityInfo EntityInfo;
        public DBAccess db;
        protected ILogger logger;
        public EntityManager(DBAccess db, EntityInfo entityInfo)
        {
            this.db = db;
            this.EntityInfo = entityInfo;
            this.logger = LoggerFactory.CreateLogger(EntityInfo.TypeFullName);
        }

        #region 基础表操作 id操作
        public void ResetId()
        {
            var tableName = EntityInfo.FullName;
            var primary = EntityInfo.EntityPropertyInfos.FirstOrDefault(i => i.IsPrimaryKey);
            var colName = primary.ColumnName;
            if (primary.PrimaryKeyStrategy != Annotations.KeyStrategy.NewId)
            {
                logger.LogWarning($"表[{tableName}]的主键[{colName}] 没有配置主键为 NewId ,但却执行 FastEntity.ResetId() 方法");
            }
            db.ResetId(tableName, colName);
        }
        public long NewId()
        {
            var tableName = EntityInfo.FullName;
            var primary = EntityInfo.EntityPropertyInfos.FirstOrDefault(i => i.IsPrimaryKey);
            var colName = primary.ColumnName;
            if (primary.PrimaryKeyStrategy != Annotations.KeyStrategy.NewId)
            {
                logger.LogWarning($"表[{tableName}]的主键[{colName}] 没有配置主键为 NewId ,但却执行 FastEntity.NewId() 方法");
            }
            return db.NewId(tableName, colName);
        }

        public List<long> NewIds(int count)
        {
            var tableName = EntityInfo.FullName;
            var primary = EntityInfo.EntityPropertyInfos.FirstOrDefault(i => i.IsPrimaryKey);
            var colName = primary.ColumnName;
            if (primary.PrimaryKeyStrategy != Annotations.KeyStrategy.NewId)
            {
                logger.LogWarning($"表[{tableName}]的主键[{colName}] 没有配置主键为 NewId ,但却执行 FastEntity.NewIds() 方法");
            }
            return db.NewIds(tableName, colName, count);
        }
        #endregion
        #region GetNow & GetUserId
        public string GetNow()
        {
            var now = db.Settings.GetExtend<EntitySetting>(EntitySetting.ExtendKey).GetNow();
            return db.ConvertToSqlSegment(now).UnWrap();
        }
        public string GetUserId()
        {
            var userId = db.Settings.GetExtend<EntitySetting>(EntitySetting.ExtendKey).GetUserIdString();
            return db.ConvertToSqlSegment(userId).UnWrap();
        }
        #endregion

    }

    /// <summary>
    /// 实体操作工具实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class EntityManager<T> : EntityManager where T : class, new()
    {
        public EntityManager(DBAccess db, EntityInfo entityInfo) : base(db, entityInfo) { }

        #region 插入
        //可以插入多个实体
        public InsertBuilder<T> InsertByEntity(IEnumerable<T> entities) => new InsertBuilder<T>(this, entities);
        public InsertBuilder<T> InsertByEntity(T entity) => new InsertBuilder<T>(this, new[] { entity });
        //确定dto类型就确定了列,可以插入多行
        public InsertBuilder<T> InsertByDto(object dto) => new InsertBuilder<T>(this, dto);
        //只支持一次插入一行
        public InsertBuilder<T> InsertByExpression(Expression<Func<T>> expression) => new InsertBuilder<T>(this, expression);
        #endregion

        #region 更改
        public UpdateBuilder<T> UpdateByEntity(IEnumerable<T> entities) => new UpdateBuilder<T>(this, entities);
        public UpdateBuilder<T> UpdateByEntity(T entity) => new UpdateBuilder<T>(this, new[] { entity });
        public UpdateBuilder<T> UpdateByExpression(Expression<Func<T, T>> expression) => new UpdateBuilder<T>(this, expression);
        public UpdateBuilder<T> UpdateByDto(object dto)
        {
            if (dto is T entity) throw new Exception("请使用 UpdateByEntity 方法! ");
            if (dto is T[] entityArray) throw new Exception("请使用 UpdateByEntity 方法! ");
            if (dto is IEnumerable<T> entityEnumerable) throw new Exception("请使用 UpdateByEntity 方法! ");
            if (dto is Expression<Func<T, T>> expression) throw new Exception("请使用 UpdateByExpression 方法! ");
            return new UpdateBuilder<T>(this, dto);
        }
        #endregion

        #region 删除
        public virtual DeleteBuilder<T> Delete(params object[] keys) => throw new NotImplementedException();
        public virtual DeleteBuilder<T> DeleteByExpression(Expression<Func<T, bool>> expression) => throw new NotImplementedException();
        #endregion

        #region 查询
        //根据主键查询
        public virtual SelectBuilder<T> Select(params object[] keys) => throw new NotImplementedException();
        public virtual SelectBuilder<T> Select() => throw new NotImplementedException();
        #endregion
    }
}
